package com.kfm.security;

import com.fasterxml.jackson.databind.json.JsonMapper;
import com.kfm.util.JwtUtil;
import com.kfm.util.Resp;
import com.kfm.util.SecurityUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.*;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.util.StringUtils;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 自定义登录流程
 * 该过滤器继承自 UsernamePasswordAuthenticationFilter
 * UsernamePasswordAuthenticationFilter 是 Spring Security 提供的默认登录过滤器
 */
@Slf4j // 日志注解
public class SecurityLoginFilter extends UsernamePasswordAuthenticationFilter {

    public SecurityLoginFilter(AuthenticationManager authenticationManager) {
        super(authenticationManager);
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
        // 从请求中获取用户名和密码
        String username = request.getParameter("username");
        String password = request.getParameter("password");

        if (!StringUtils.hasText(username) || !StringUtils.hasText(password)){
            throw new RuntimeException("用户名或密码不能为空");
        }

        // 调用封装的工具类进行登录
        SecurityUtil.login(username, password, getAuthenticationManager());

        return SecurityUtil.getAuthentication();
    }

    /**
     * 重写 successfulAuthentication 方法
     * 该方法会在认证成功后调用
     * @param request
     * @param response
     * @param chain
     * @param authResult the object returned from the <tt>attemptAuthentication</tt>
     * method.
     * @throws IOException
     * @throws ServletException
     */
    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
        Object principal = authResult.getPrincipal();

        log.info("principal: {}", principal);

        JsonMapper jsonMapper = new JsonMapper();
        // 生成 jwt
        String jwt = JwtUtil.sign(jsonMapper.writeValueAsString(principal));

        response.setHeader("Authorization", jwt);
        response.setContentType("application/json;charset=utf-8");

        response.getWriter().write(jsonMapper.writeValueAsString(Resp.ok(jwt)));
    }


    @Override
    protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) throws IOException, ServletException {
        log.error("登录失败, {}", e);

        Resp result;
        if (e instanceof AccountExpiredException) {
            //账号过期
            result = Resp.error("账号过期");
        } else if (e instanceof BadCredentialsException) {
            //密码错误
            result = Resp.error("密码错误");
        } else if (e instanceof CredentialsExpiredException) {
            //密码过期
            result = Resp.error("密码过期");
        } else if (e instanceof DisabledException) {
            //账号不可用
            result = Resp.error("账号不可用");
        } else if (e instanceof LockedException) {
            //账号锁定
            result = Resp.error("账号锁定");
        } else if (e instanceof InternalAuthenticationServiceException) {
            //用户不存在
            result = Resp.error("用户不存在");
        }else{
            //其他错误
            result = Resp.error("未知异常");
        }

        response.setContentType("application/json;charset=utf-8");
        JsonMapper jsonMapper = new JsonMapper();

        response.getWriter().write(jsonMapper.writeValueAsString(result));
    }

}
